package com.yeskery.nut.cloud.feign;

import com.yeskery.nut.annotation.cloud.feign.FeignClient;
import com.yeskery.nut.annotation.web.*;
import com.yeskery.nut.application.NutApplication;
import com.yeskery.nut.bean.ApplicationContext;
import com.yeskery.nut.bean.BeanHolder;
import com.yeskery.nut.bean.NoSuchBeanException;
import com.yeskery.nut.bind.HttpResponseBodyMetadata;
import com.yeskery.nut.bind.TextableHttpResponseBodyHandler;
import com.yeskery.nut.cloud.loadbanlancer.Breaker;
import com.yeskery.nut.cloud.loadbanlancer.Chooser;
import com.yeskery.nut.cloud.loadbanlancer.RandomChooser;
import com.yeskery.nut.cloud.loadbanlancer.Recorder;
import com.yeskery.nut.cloud.registry.core.Instance;
import com.yeskery.nut.cloud.registry.core.ServerRegistry;
import com.yeskery.nut.core.*;
import com.yeskery.nut.http.HttpMediaTypeNotSupportException;
import com.yeskery.nut.plugin.BindContext;
import com.yeskery.nut.scan.controller.AnnotationRequestMethodAttributes;
import com.yeskery.nut.util.ExpressionUtils;
import com.yeskery.nut.util.FormDataUtils;
import com.yeskery.nut.util.ReflectUtils;
import com.yeskery.nut.util.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

/**
 * feign客户端代理类处理器
 * @author sunjay
 * 2024/1/7
 */
public class FeignClientProxyInvocationHandler implements InvocationHandler {

    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(FeignClientProxyInvocationHandler.class.getName());

    /** 路径分隔符 */
    private static final String FOLDER_SEPARATOR = "/";

    /** 应用上下文 */
    private final ApplicationContext applicationContext;

    /** feign客户端元数据 */
    private final FeignClientMetadata feignClientMetadata;

    /** 方法的请求元数据map */
    private final Map<String, FeignRequestMetadata> feignRequestMetadataMap;

    /** 缓存map */
    private final Map<Class<?>, Object> cacheMap = new HashMap<>();

    /** 熔断器 */
    private Breaker breaker;

    /** 是否已初始化熔断器 */
    private volatile boolean initBreaker = false;

    /**
     * 构建feign客户端代理类处理器
     * @param applicationContext 应用上下文
     * @param feignClientMetadata feign客户端元数据
     * @param feignRequestMetadataMap 方法的请求元数据map
     */
    public FeignClientProxyInvocationHandler(ApplicationContext applicationContext, FeignClientMetadata feignClientMetadata,
                                             Map<String, FeignRequestMetadata> feignRequestMetadataMap) {
        this.applicationContext = applicationContext;
        this.feignClientMetadata = feignClientMetadata;
        this.feignRequestMetadataMap = feignRequestMetadataMap;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        switch (method.getName()) {
            case "equals":
                try {
                    Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                    return equals(otherHandler);
                } catch (IllegalArgumentException e) {
                    return false;
                }
            case "hashCode":
                return hashCode();
            case "toString":
                return toString();
        }
        FeignRequestMetadata feignRequestMetadata = feignRequestMetadataMap.get(ReflectUtils.getMethodUniqueName(method));
        if (feignRequestMetadata == null) {
            throw new FeignClientException("Feign Client[" + feignClientMetadata.getType().getName() + "] Method["
                    + method.getName() + "] Not Support.");
        }

        FeignClient feignClient = feignClientMetadata.getFeignClient();
        FeignClientRequestData feignRequestData = null;
        Throwable throwable = null;
        try {
            feignRequestData = getFeignRequestData(method.getParameters(), args, feignRequestMetadata);
        } catch (Throwable e) {
            throwable = e;
        }
        Instance instance = null;
        if (feignRequestData != null) {
            feignRequestData.setFeignClient(feignClient);
            instance = feignRequestData.getInstance();
        }
        boolean isMicroServiceInvoke = StringUtils.isEmpty(feignClient.url());
        RecordStats recordStats = new RecordStats();
        if (isMicroServiceInvoke) {
            Breaker circuitBreaker = getBreaker();
            if (circuitBreaker != null && circuitBreaker.shouldBreak(instance)) {
                return executeFallBack(feignClient.breakerCallback(), null, null, method, args);
            }
        }
        Collection<Recorder> recorders = Collections.emptyList();
        if (isMicroServiceInvoke) {
            recorders = applicationContext.getBeans(Recorder.class);
        }
        try {
            if (throwable != null) {
                throw throwable;
            }
            // 开始执行前
            if (isMicroServiceInvoke) {
                for (Recorder recorder : recorders) {
                    try {
                        recorder.start(recordStats, instance);
                    } catch (Exception e) {
                        logger.logp(Level.SEVERE, recorder.getClass().getName(), "start", "The Record["
                                + recorder.getClass().getName() + "] Execute Fail.", e);
                    }
                }
            }
            // 执行
            recordStats.setStartTime(System.currentTimeMillis());
            Object result = getOriginalRequestResult(feignRequestMetadata, feignRequestData);
            recordStats.setEndTime(System.currentTimeMillis());
            recordStats.setSuccess();
            // 执行后
            if (isMicroServiceInvoke) {
                for (Recorder recorder : recorders) {
                    try {
                        recorder.success(recordStats, instance);
                    } catch (Exception e) {
                        logger.logp(Level.SEVERE, recorder.getClass().getName(), "success", "The Record["
                                + recorder.getClass().getName() + "] Execute Fail.", e);
                    }
                }
            }
            return result;
        } catch (Throwable e) {
            recordStats.setFailTime(System.currentTimeMillis());
            // 失败后
            if (isMicroServiceInvoke) {
                for (Recorder recorder : recorders) {
                    try {
                        recorder.failure(recordStats, instance, e);
                    } catch (Exception e1) {
                        logger.logp(Level.SEVERE, recorder.getClass().getName(), "failure", "The Record["
                                + recorder.getClass().getName() + "] Execute Fail.", e1);
                    }
                }
            }
            return executeFallBack(feignClient.callback(), feignClient.fallbackFactory(), e, method, args);
        }
    }

    /**
     * 执行失败回调
     * @param callbackClass 发生熔断时的回调处理类
     * @param fallbackFactoryClass 发生熔断时的回调工厂类
     * @param throwable 异常对象
     * @param method 方法对象
     * @param args 方法参数数组
     * @return 回调执行结果
     */
    private Object executeFallBack(Class<?> callbackClass, Class<?> fallbackFactoryClass, Throwable throwable, Method method, Object[] args) {
        if (callbackClass != null && !void.class.equals(callbackClass)) {
            if (!feignClientMetadata.getType().isAssignableFrom(callbackClass)) {
                throw new FeignClientException("Feign Client Callback Class Must Implement [" + feignClientMetadata.getType().getName() + "].");
            }
            Object target = ReflectUtils.getNoConstructorTarget(cacheMap, callbackClass);
            return ReflectUtils.invokeSpecifiedMethod(target, method, args);
        }
        if (fallbackFactoryClass != null && !void.class.equals(fallbackFactoryClass)) {
            if (!FallbackFactory.class.isAssignableFrom(fallbackFactoryClass)) {
                throw new FeignClientException("Feign Client Callback Factory Class Must Implement [" + FallbackFactory.class.getName() + "].");
            }
            Object target = ReflectUtils.getNoConstructorTarget(cacheMap, fallbackFactoryClass);
            target = ((FallbackFactory<?>) target).create(throwable);
            if (target == null || !feignClientMetadata.getType().isAssignableFrom(target.getClass())) {
                throw new FeignClientException("Feign Client Callback Factory Class Instance Must Implement [" + feignClientMetadata.getType().getName() + "].");
            }
            return ReflectUtils.invokeSpecifiedMethod(target, method, args);
        }
        throw throwable == null ? new FeignClientException("Feign Client Execute Fail.") : new FeignClientException("Feign Client Execute Fail.", throwable);
    }

    /**
     * 获取远程请求执行结果
     * @param feignRequestMetadata feign请求元数据
     * @param feignRequestData 获取feign请求数据
     * @return 远程请求执行结果
     */
    private Object getOriginalRequestResult(FeignRequestMetadata feignRequestMetadata, FeignRequestData feignRequestData) {
        FeignRequestHandler feignRequestHandler = applicationContext.getBean(FeignRequestHandler.class);
        return feignRequestHandler.handle(feignRequestMetadata, feignRequestData);
    }

    /**
     * 获取feign请求数据
     * @param parameters 参数类型数组
     * @param args 参数对象数组
     * @param feignRequestMetadata feign请求元数据
     * @return feign请求数据
     */
    private FeignClientRequestData getFeignRequestData(Parameter[] parameters, Object[] args, FeignRequestMetadata feignRequestMetadata) {
        FeignClientRequestData feignRequestData = new FeignClientRequestData();
        FeignInstanceUrl feignInstanceUrl = getFeignInstanceUrl(feignRequestMetadata);
        feignRequestData.setInstance(feignRequestData.getInstance());
        BeanHolder requestUrlBeanHolder = new BeanHolder(String.class, feignInstanceUrl.getUrl());
        Map<Integer, RequestAnnotationType> requestAnnotationTypeMap = feignRequestMetadata.getRequestAnnotationTypeMap();

        // 处理路径参数
        requestAnnotationTypeMap.entrySet()
                .stream()
                .filter(e -> PathVariable.class.equals(e.getValue().getAnnotationType()))
                .map(e -> {
                    if (args[e.getKey()] == null) {
                        return null;
                    }
                    PathVariable pathVariable = (PathVariable) e.getValue().getAnnotation();
                    String name = StringUtils.isEmpty(pathVariable.value()) ? parameters[e.getKey()].getName() : pathVariable.value();
                    return new NameAndValue(name, args[e.getKey()].toString());
                })
                .filter(Objects::nonNull)
                .forEach(e -> requestUrlBeanHolder.setObject(requestUrlBeanHolder.getObject().toString().replace("{" + e.getKey() + "}", e.getValue())));

        // 处理请求头参数
        List<NameAndValue> headers = requestAnnotationTypeMap.entrySet()
                .stream()
                .filter(e -> RequestHeader.class.equals(e.getValue().getAnnotationType()))
                .map(e -> {
                    if (args[e.getKey()] == null) {
                        return null;
                    }
                    RequestHeader requestHeader = (RequestHeader) e.getValue().getAnnotation();
                    String name = StringUtils.isEmpty(requestHeader.value()) ? parameters[e.getKey()].getName() : requestHeader.value();
                    return new NameAndValue(name, args[e.getKey()].toString());
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        // 处理cookie参数
        String cookies = requestAnnotationTypeMap.entrySet()
                .stream()
                .filter(e -> CookieValue.class.equals(e.getValue().getAnnotationType()))
                .map(e -> {
                    if (args[e.getKey()] == null) {
                        return null;
                    }
                    CookieValue cookieValue = (CookieValue) e.getValue().getAnnotation();
                    String name = StringUtils.isEmpty(cookieValue.value()) ? parameters[e.getKey()].getName() : cookieValue.value();
                    return new NameAndValue(name, args[e.getKey()].toString());
                })
                .filter(Objects::nonNull)
                .map(e -> e.getKey() + "=" + e.getValue())
                .collect(Collectors.joining(";"));
        if (!StringUtils.isEmpty(cookies)) {
            headers.add(new NameAndValue(HttpHeader.COOKIE, cookies));
        }

        // 处理请求参数
        List<NameAndValue> params = Collections.emptyList();
        if (requestAnnotationTypeMap.entrySet()
                .stream()
                .filter(e -> RequestParam.class.equals(e.getValue().getAnnotationType()))
                .filter(e -> args[e.getKey()] != null)
                .anyMatch(e -> (args[e.getKey()] instanceof MultipartFile))) {
            List<FormDataUtils.FormDataItem> formDataItems = new ArrayList<>(requestAnnotationTypeMap.size());
            for (Map.Entry<Integer, RequestAnnotationType> entry : requestAnnotationTypeMap.entrySet()) {
                if (RequestParam.class.equals(entry.getValue().getAnnotationType()) && args[entry.getKey()] != null) {
                    RequestParam requestParam = (RequestParam) entry.getValue().getAnnotation();
                    String name = StringUtils.isEmpty(requestParam.value())
                            ? parameters[entry.getKey()].getName() : requestParam.value();
                    if (args[entry.getKey()] instanceof MultipartFile) {
                        MultipartFile multipartFile = (MultipartFile) args[entry.getKey()];
                        formDataItems.add(FormDataUtils.createFileFormDataItem(name, multipartFile.getFileName(),
                                multipartFile.getContentType(), multipartFile.getData()));
                    } else {
                        formDataItems.add(FormDataUtils.createNormalFormDataItem(name, args[entry.getKey()].toString().getBytes()));
                    }
                }
            }
            FormDataUtils.FormData formData = FormDataUtils.createFormData(formDataItems);
            headers.add(new NameAndValue(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_FORM_DATA.getValue() + "; boundary=" + formData.getBoundary()));
            feignRequestData.setBodyResource(() -> new ByteArrayInputStream(formData.getBytes()));
        } else {
            params = requestAnnotationTypeMap.entrySet()
                    .stream()
                    .filter(e -> RequestParam.class.equals(e.getValue().getAnnotationType()))
                    .map(e -> {
                        if (args[e.getKey()] == null) {
                            return null;
                        }
                        RequestParam requestParam = (RequestParam) e.getValue().getAnnotation();
                        String name = StringUtils.isEmpty(requestParam.value()) ? parameters[e.getKey()].getName() : requestParam.value();
                        return new NameAndValue(name, args[e.getKey()].toString());
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            if (!params.isEmpty()) {
                String[] consumes = feignRequestMetadata.getConsumes();
                if (consumes != null && consumes.length > 0 && MediaType.APPLICATION_FORM_DATA.getValue().equals(consumes[0])) {
                    List<FormDataUtils.FormDataItem> formDataItems = new ArrayList<>(params.size());
                    for (NameAndValue nameAndValue : params) {
                        formDataItems.add(FormDataUtils.createNormalFormDataItem(nameAndValue.getKey(), nameAndValue.getValue().getBytes()));
                    }
                    FormDataUtils.FormData formData = FormDataUtils.createFormData(formDataItems);
                    headers.add(new NameAndValue(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_FORM_DATA.getValue() + "; boundary=" + formData.getBoundary()));
                    feignRequestData.setBodyResource(() -> new ByteArrayInputStream(formData.getBytes()));
                }
            }
        }

        // 处理请求体
        requestAnnotationTypeMap.entrySet()
                .stream()
                .filter(e -> RequestBody.class.equals(e.getValue().getAnnotationType()))
                .findFirst()
                .ifPresent(e -> {
                    Object param = args[e.getKey()];
                    if (args[e.getKey()] != null) {
                        if (InputStreamResource.class.isAssignableFrom(param.getClass())) {
                            headers.add(new NameAndValue(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM.getValue()));
                            feignRequestData.setBodyResource((InputStreamResource) param);
                        } else {
                            List<TextableHttpResponseBodyHandler> httpResponseBodyHandlers = applicationContext.getBean(NutApplication.class)
                                    .getNutWebConfigure().getHttpResponseBodyHandlers()
                                    .stream()
                                    .filter(r -> r instanceof TextableHttpResponseBodyHandler)
                                    .map(r -> (TextableHttpResponseBodyHandler) r)
                                    .sorted(Comparator.comparing(Order::getOrder))
                                    .collect(Collectors.toList());
                            HttpResponseBodyMetadata metadata = new HttpResponseBodyMetadata();
                            metadata.setApplicationContext(applicationContext);
                            metadata.setBindContext(new FeignBindContext(applicationContext));
                            metadata.setRequest(new UnSupportRequest());
                            metadata.setResponse(new UnSupportResponse());
                            AnnotationRequestMethodAttributes attributes = new AnnotationRequestMethodAttributes();
                            attributes.setConsumes(feignRequestMetadata.getProduces());
                            attributes.setProduces(feignRequestMetadata.getConsumes());
                            metadata.setAttributes(attributes);
                            metadata.setResult(param);
                            boolean handled = false;
                            String result = null;
                            for (TextableHttpResponseBodyHandler handler : httpResponseBodyHandlers) {
                                if (handler.support(metadata)) {
                                    result = handler.getExtractText(metadata);
                                    handled = true;
                                    break;
                                }
                            }
                            if (!handled) {
                                throw new HttpMediaTypeNotSupportException("ResponseEntity[type=" + param.getClass().getName()
                                        + "] Consume Media Type[" + String.join(", ", feignRequestMetadata.getConsumes()) + "] Not Support.");
                            }
                            if (!StringUtils.isEmpty(result)) {
                                headers.add(new NameAndValue(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue()));
                                feignRequestData.setBodyString(result);
                            }
                        }
                    }
                });

        if (!params.isEmpty() && headers.stream().noneMatch(e -> HttpHeader.CONTENT_TYPE.equals(e.getKey()))) {
            headers.add(new NameAndValue(HttpHeader.CONTENT_TYPE, MediaType.APPLICATION_X_WWW_FORM_URLENCODED.getValue()));
        }
        String[] consumes = feignRequestMetadata.getConsumes();
        if (consumes != null && consumes.length > 0) {
            ListIterator<NameAndValue> iterator = headers.listIterator();
            boolean reset = false;
            while (iterator.hasNext()) {
                NameAndValue nameAndValue = iterator.next();
                if (HttpHeader.CONTENT_TYPE.equals(nameAndValue.getKey())) {
                    iterator.set(new NameAndValue(HttpHeader.CONTENT_TYPE, consumes[0]));
                    reset = true;
                    break;
                }
            }
            if (!reset) {
                headers.add(new NameAndValue(HttpHeader.CONTENT_TYPE, consumes[0]));
            }
        }
        String[] produces = feignRequestMetadata.getProduces();
        if (produces != null && produces.length > 0) {
            ListIterator<NameAndValue> iterator = headers.listIterator();
            boolean reset = false;
            while (iterator.hasNext()) {
                NameAndValue nameAndValue = iterator.next();
                if (HttpHeader.ACCEPT.equals(nameAndValue.getKey())) {
                    iterator.set(new NameAndValue(HttpHeader.ACCEPT, String.join(",", produces)));
                    reset = true;
                    break;
                }
            }
            if (!reset) {
                headers.add(new NameAndValue(HttpHeader.ACCEPT, String.join(",", produces)));
            }
        }

        feignRequestData.setUrl(requestUrlBeanHolder.getObject().toString());
        feignRequestData.setHeaders(headers);
        feignRequestData.setParams(params);
        return feignRequestData;
    }

    /**
     * 获取feign服务实例url对象
     * @param feignRequestMetadata feign请求元数据
     * @return feign服务实例url对象
     */
    private FeignInstanceUrl getFeignInstanceUrl(FeignRequestMetadata feignRequestMetadata) {
        FeignInstanceUrl feignInstanceUrl = new FeignInstanceUrl();
        FeignClient feignClient = feignClientMetadata.getFeignClient();
        String baseUrl;
        if (StringUtils.isEmpty(feignClient.url())) {
            // 使用服务发现进行服务调用
            ServerRegistry serverRegistry;
            try {
                serverRegistry = applicationContext.getBean(ServerRegistry.class);
            } catch (NoSuchBeanException e) {
                throw new FeignClientException("Server Registry Not Enabled.");
            }
            Chooser chooser;
            try {
                chooser = applicationContext.getBean(Chooser.class);
            } catch (NoSuchBeanException e) {
                logger.info("Chooser Obtain Fail. Current Use [" + RandomChooser.class.getName() + "] Cause: " + e.getMessage());
                chooser = new RandomChooser();
            }
            Instance instance = chooser.choose(serverRegistry.getServer(feignClient.name()));
            feignInstanceUrl.setInstance(instance);
            baseUrl = instance.getScheme() + instance.getIp() + ":" + instance.getPort();
        } else {
            baseUrl = feignClient.url();
            if (!StringUtils.isEmpty(baseUrl) && ExpressionUtils.isExpression(baseUrl.trim())) {
                baseUrl = ExpressionUtils.getExpressValue(applicationContext.getBean(Environment.class), baseUrl, null);
            }
        }
        if (StringUtils.isEmpty(baseUrl)) {
            throw new FeignClientException("Request Url Can Not Be Empty.");
        }
        if (baseUrl.endsWith(FOLDER_SEPARATOR)) {
            baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
        }
        String requestUrl = feignRequestMetadata.getUrl();
        if (!requestUrl.startsWith(FOLDER_SEPARATOR)) {
            requestUrl = FOLDER_SEPARATOR + requestUrl;
        }
        feignInstanceUrl.setUrl(baseUrl + requestUrl);
        return feignInstanceUrl;
    }

    /**
     * 获取熔断器对象
     * @return 熔断器对象
     */
    private Breaker getBreaker() {
        if (initBreaker) {
            return breaker;
        }
        synchronized (this) {
            if (!initBreaker) {
                try {
                    breaker = applicationContext.getBean(Breaker.class);
                } catch (NoSuchBeanException e) {
                    // Not Deal.
                }
                initBreaker = true;
            }
        }
        return breaker;
    }

    /**
     * feign服务实例url对象
     * @author sunjay
     * 2024/1/17
     */
    private static final class FeignInstanceUrl {

        /** 服务实例对象 */
        private Instance instance;

        /** 请求url */
        private String url;

        /**
         * 获取服务实例对象
         * @return 服务实例对象
         */
        public Instance getInstance() {
            return instance;
        }

        /**
         * 设置服务实例对象
         * @param instance 服务实例对象
         */
        public void setInstance(Instance instance) {
            this.instance = instance;
        }

        /**
         * 获取请求url
         * @return 请求url
         */
        public String getUrl() {
            return url;
        }

        /**
         * 设置请求url
         * @param url 请求url
         */
        public void setUrl(String url) {
            this.url = url;
        }
    }

    /**
     * Feign绑定上下文对象
     * @author sunjay
     * 2025/8/22
     */
    private static class FeignBindContext implements BindContext {

        /** nut应用对象 */
        private final NutApplication nutApplication;

        /** 绑定上下文对象 */
        private final BindContext bindContext;

        /**
         * 构造不支持的绑定上下文对象
         * @param applicationContext 应用上下文对象
         */
        private FeignBindContext(ApplicationContext applicationContext) {
            this.nutApplication = applicationContext.getBean(NutApplication.class);
            this.bindContext = applicationContext.getBean(BindContext.class);
        }

        @Override
        public NutApplication getNutApplication() {
            return nutApplication;
        }

        @Override
        public void bindObject(Class<?> clazz, Object object) {
            bindContext.bindObject(clazz, object);
        }

        @Override
        public <T> T getObject(Class<T> clazz) {
            return bindContext.getObject(clazz);
        }
    }

    /**
     * 不支持的请求对象
     * @author sunjay
     * 2025/8/22
     */
    private static class UnSupportRequest implements Request {

        @Override
        public List<String> getHeaders(String key) {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Map<String, List<String>> getHeaders() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Set<String> getParameterKeys() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public com.yeskery.nut.core.Method getMethod() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getOriginalPath() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getPath() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getProtocol() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Cookie[] getCookies() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public List<MultipartFile> getFiles(String key) {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public byte[] getBody() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Map<String, List<String>> getParametersMap() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Map<String, List<String>> getQueryParametersMap() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Session getSession() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public ServerContext getServerContext() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public boolean isEmpty() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public void addAttribute(String name, Object object) {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public void removeAttribute(String name) {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Object getAttribute(String name) {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public Map<String, Object> getAttributes() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getRemoteAddress() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getRemoteHost() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public int getRemotePort() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getLocalAddress() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public String getLocalHost() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public int getLocalPort() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }

        @Override
        public ServerRequestConfiguration getServerRequestConfiguration() {
            throw new UnsupportedOperationException("Feign Not Support Request Method.");
        }
    }

    /**
     * 不支持的响应对象
     * @author sunjay
     * 2025/8/22
     */
    private static class UnSupportResponse implements Response {

        @Override
        public void setCode(int code) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void setCharSet(String charSet) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void addHeader(NameAndValue nameAndValue) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void addCookie(Cookie cookie) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void writeEmpty() {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(InputStream inputStream) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(InputStream inputStream, MediaType mediaType) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(InputStream inputStream, String mediaType) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(byte[] bytes) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(byte[] bytes, MediaType mediaType) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(byte[] bytes, String mediaType) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(String content) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void writeHtml(String content) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void writeXml(String content) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void writeJson(String content) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void writeJsonFromObject(Object object) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public void write(String content, MediaType mediaType) {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }

        @Override
        public boolean isResponse() {
            throw new UnsupportedOperationException("Feign Not Support Response Method.");
        }
    }
}
